
#include <jbk/physics/cpm/Cell.h>
#include <jbk/physics/cpm/grid/CheckersGrid.h>
#include <jbk/physics/cpm/display/Color.h>
#include <jbk/physics/cpm/display/OpenGlWorldDisplay.h>
#include <jbk/physics/cpm/display/Palette.h>
#include <jbk/physics/cpm/Physics.h>
#include <jbk/physics/cpm/World.h>

void demo() {

	/* World */
	int worldWidth  = 300;
	int worldHeight = 300;
	World world(worldWidth, worldHeight);

	/* physics */
	Physics physics(world);
//	int developmentalIterations = 4000;

//	physics.getParameters().setSizeEnergyCoef(0.0);
	physics.getParameters().setAdhesionEnergyCoef(100000.0);

	/* palette */
	Palette palette;
	palette.setColor(0, Color::White);
	palette.setColor(1, Color::Black);
	palette.setColor(2, Color::Blue);
	palette.setColor(3, Color::Green);
	palette.setColor(4, Color::Grey);
	palette.setColor(5, Color::Yellow);
	palette.setColor(6, Color::Magenta);
	palette.setColor(7, Color::Cyan);
	palette.setColor(8, Color::Teal);
	palette.setColor(9, Color::Navy);
	palette.setColor(10, Color::Red);
	palette.setColor(11, Color::Salmon);
	palette.setColor(12, Color::Purple);
	palette.setColor(13, Color::SeaGreen);
	palette.setColor(14, Color::SlateBlue);
	palette.setColor(15, Color::SpringGreen);
	palette.setColor(16, Color::Tomato);

	/* substrate mapping */
	palette.setMappingFromTo(0, 0);

//	int choice = 0;
	int choice = 1;
	switch(choice) {
		case 0: {
			/* create a square cell */
			int side = 4;
			Cell* cell = Cell::newCellSquare(world, (worldWidth - side) / 2, (worldHeight - side) / 2, side);
			palette.setMappingFromTo(cell->getId(), 10);
	//		cell->setAdhesionKeyLock(0, 31);

			/* set its desired size bigger */
			cell->setTargetSize(10000);

//			cell->setMembraneRigidity(1000000000.0);
//			cell->setMembraneRigidity(0.0000000001);
			cell->setMembraneRigidity(100.0);
			break;
		}
		case 1: {
			/* checkers cells 2 types */

			/* dimensions */
			int checkersWidth      = 4;
			int checkersHeight     = 4;
			int checkersTileSide   = 12;
			int checkersTargetSize = 1000;

			/* cell generation */
			Cell** cells = Cell::newCellCheckers(
				world,
				worldWidth  / 2 - (checkersWidth  * checkersTileSide) / 2,
				worldHeight / 2 - (checkersHeight * checkersTileSide) / 2,
				checkersWidth,
				checkersHeight,
				checkersTileSide);

			/* cell setup */
			for(int i = 0; i != checkersWidth; ++i) {
				for(int j = 0; j != checkersHeight; ++j) {
					/* cell */
					Cell& cell = *(cells[j * checkersWidth + i]);

					cell.setTargetSize(1000);
					/* cell type */
					int type = 1 + (i + j) % 2;

					/* palette mapping */
					palette.setMappingFromTo(cell.getId(), cell.getId());

//					/* cell membrane */
					if (type == 1) {
						cell.setMembraneRigidity(1000.0);
					} else {
						cell.setMembraneRigidity(0.1);
					}
					cell.setMembraneRigidity(100.0);
						
					/* cell adhesion */
					if (type == 1) {
						cell.setAdhesionKeyLock(0, 0);
					} else {
						cell.setAdhesionKeyLock(15, 15);
					}
		//			cell.setAdhesionKeyLock(127, 127);

					/* target size */
					cell.setTargetSize(checkersTargetSize);
				}
			}

			/* clean up */
			delete cells;
			break;
		}
	}


	/* checkers cells */
//	int checkersWidth  = 3;
//	int checkersHeight = 3;
//	int checkersTileSide = 10;
//	int checkersTargetSize = 300;
//	Cell** cells = Cell::newCellCheckers(
//		physicsModelWidth  / 2 - (checkersWidth  * checkersTileSide) / 2,
//		physicsModelHeight / 2 - (checkersHeight * checkersTileSide) / 2,
//		checkersWidth,
//		checkersHeight,
//		checkersTileSide);
//	for(int i = 0; i != checkersWidth * checkersHeight; ++i) {
//		Cell* cell = cells[i];
//		int cellId = cell->getId();
//		cell->setTargetSize(checkersTargetSize);
//		palette.setMappingFromTo(cellId, cellId);
//		physicsModel.addCell(cell);
//	}


	/* Display */
	OpenGlWorldDisplay display(world, physics);
	display.setPalette(palette);

	display.run();
}

int main(int, char**) {
	demo();

	return 0;
}

